﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using Caliburn.Micro;

using Ingenious.Graph;

namespace Ingenious.Core
{
    public interface INameValuePair : INotifyPropertyChanged
    {
        string Name { get; }
        object Value { get; }
        bool IsLiteral { get; }
    }

    // Used for exposing the properties of a node
    // as a bindable, writable list of name-value pairs
    public class NameValuePair<TTripleId> : PropertyChangedBase, INameValuePair
    {
        private readonly Node<TTripleId> m_parent;
        private readonly KeyValuePair<string, NodePropertyInfo<TTripleId>> m_keyValuePair;

        #region Object Lifetime
        public NameValuePair(Node<TTripleId> parent, KeyValuePair<string, NodePropertyInfo<TTripleId>> keyValuePair)
        {
            if (parent == null)
            {
                throw new ArgumentNullException("parent");
            }

            m_parent = parent;
            m_keyValuePair = keyValuePair;

            m_parent.PropertyChanged += OnParentNodePropertyChanged;
        }
        #endregion

        private void OnParentNodePropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            if (e.PropertyName == Name)
            {
                NotifyOfPropertyChange(() => Value);
            }
        }

        #region Properties
        public string Name
        {
            get { return m_keyValuePair.Key; }
        }

        // Wrapper helper property
        public object Value
        {
            get
            {
                if (IsLiteral)
                {
                    return m_keyValuePair.Value.LiteralValue;
                }

                return m_keyValuePair.Value.Value;
            }
            set
            {
                if (IsLiteral)
                {
                    if (m_keyValuePair.Value.LiteralValue != value)
                    {
                        m_keyValuePair.Value.LiteralValue = value;
                        NotifyOfPropertyChange(() => Value);
                    }
                }
                else
                {
                    if (m_keyValuePair.Value.Value != value)
                    {
                        // Set the original value on the parent key-value dictionary
                        m_keyValuePair.Value.Value = value;
                        NotifyOfPropertyChange(() => Value);
                    }
                }
            }
        }

        public bool IsLiteral
        {
            get { return m_keyValuePair.Value.LiteralValue != null; }
        }

        public NodePropertyInfo<TTripleId> PropertyInfo
        {
            get { return m_keyValuePair.Value; }
        }
        #endregion
    }
}
